package token

import (
	"encoding/json"
	"fmt"
	"github.com/tidwall/gjson"
	"io/ioutil"
	"log"
	"strings"
	"sync"
)

// AccessToken ...
type AccessToken struct {
	gjson.Result
	//source gjson.Result
	name   string //读取名称
	path   string //数据路径
}
var rwMutex sync.RWMutex

type Option func(file *AccessToken)

func WithPath(path string) Option {
	return func(file *AccessToken) {
		if path != FieldEmpty {
			file.path = path
		}
	}
}

func NewToken(f ...Option) *AccessToken {
	rwMutex.RLock()
	defer rwMutex.RUnlock()
	t := &AccessToken{
		path: TokenFilePath,
	}
	for _, i2 := range f {
		i2(t)
	}
	jsonFile, err := ioutil.ReadFile(t.path)
	if err != nil {
		log.Fatalf("无法读取JSON文件: %v", err)
	}
	t.Result = gjson.ParseBytes(jsonFile)
	return t
}

func (a *AccessToken) insert(value map[string]interface{}) error {
	rwMutex.Lock()
	defer rwMutex.Unlock()
	valueString,err := json.Marshal(value)
	err = ioutil.WriteFile(a.path, valueString, 0644)
	if err != nil {
		return err
	}
	return nil
}

func (a *AccessToken) Get(s string) *AccessToken {
	if s != FieldEmpty {
		if a.name != FieldEmpty {
			a.name = a.name + "." + s
		} else {
			a.name = s
		}
	}
	sour := a.Result
	if a.name != FieldEmpty {
		sour = sour.Get(a.name)
	}
	return a
}

func (a *AccessToken) String() string {
	return a.Result.Get(a.name).String()
}
func (a *AccessToken) Map() map[string]gjson.Result {
	return a.Result.Get(a.name).Map()
}

func (a *AccessToken) Value() interface{} {
	return a.Result.Get(a.name).Value()
}

func (a *AccessToken) Exists() bool {
	return a.Result.Get(a.name).Exists()
}

func (a *AccessToken) GetInt64(s string) int64 {
	return a.Get(s).Int()
}

func (a *AccessToken) GetByte(s string) []byte {
	return []byte(a.Get(s).String())
}

func (a *AccessToken) GetString(s string) string {
	return a.Get(s).String()
}

func (a *AccessToken) GetStruct(s string, source interface{}) error {
	return json.Unmarshal([]byte(a.Get(s).String()), source)
}

func (a *AccessToken) GetMap(s string) (map[string]interface{}, error) {
	var value map[string]interface{}
	err := json.Unmarshal([]byte(a.Get(s).String()), &value)
	return value, err
}

func (a *AccessToken) Set(s interface{}) (bool, error) {
	var value map[string]interface{}

	err := json.Unmarshal([]byte(a.Result.String()), &value)
	if err != nil {
		return false, err
	}
	list := strings.Split(a.name,".")
	err = setValue(&value,s,list,0)
	if err != nil {
		return false, err
	}
	err = a.insert(value)
	if err != nil {
		return false, err
	}
	return true, nil
}

func (a *AccessToken) SetInt(s int) (bool, error) {
	return a.Set(s)
}
func (a *AccessToken) SetInt32(s int32) (bool, error) {
	return a.Set(s)
}
func (a *AccessToken) SetByte(s []byte) (bool, error) {
	return a.Set(s)
}
func (a *AccessToken) SetString(s string) (bool, error) {
	return a.Set(s)
}

func (a *AccessToken) SetStruct(s interface{}) (bool, error) {
	return a.Set(s)
}

func (a *AccessToken) SetMap(s interface{}) (bool, error) {
	return a.Set(s)
}



func setValue(source *map[string]interface{} ,value interface{},list []string,idx int) error {
	key := ""
	if len(list) >= idx + 1 {
		key = list[idx]
	}

	if _,ok := (*source)[key];!ok {
		return fmt.Errorf("源数据不存在：%s,字段:%s", (*source)[key],key)
	}
	if len(list) == idx + 1 {
		(*source)[key] = value
		return nil
	}
	if _,ok := (*source)[key].(map[string]interface{});!ok {
		return fmt.Errorf("源数据不存在：%s", (*source)[key])
	}
	val := (*source)[key].(map[string]interface{})
	return setValue(&val,value,list,idx+1)
}